﻿using System;
using System.Diagnostics;
using System.Text;
using Muccu.Contracts;

namespace Muccu
{
    internal class Tracer
    {
        private static TraceSource _trace = new TraceSource("Muccu");

        public static void StartOperation(string text)
        {
            _trace.TraceEvent(TraceEventType.Information, EventID.StartOperation, text);
        }

        public static void EndOperation(string text)
        {
            _trace.TraceEvent(TraceEventType.Information, EventID.EndOperation, text);
        }

        /// <summary>
        /// Writes information message to the tracelisteners.
        /// </summary>
        public static void WriteMessage(string format, params object[] args)
        {
            _trace.TraceEvent(TraceEventType.Information, EventID.Trace, format, args);
        }

        /// <summary>
        /// Writes verbose message to tracelisteners.
        /// </summary>
        public static void WriteTrace(string format, params object[] args)
        {
            _trace.TraceEvent(TraceEventType.Verbose, EventID.Trace, format, args);
        }

        public static void WriteException(Exception ex)
        {
            _trace.TraceData(TraceEventType.Error, EventID.UnhandledException, ex);
        }

        public static void WriteHandledException(Exception ex)
        {
            _trace.TraceData(TraceEventType.Error, EventID.HandledException, ex);
        }

        class EventID
        {
            public static int Trace = 0;
            public static int StartOperation = 1;
            public static int EndOperation = 2;
            public static int UnhandledException = 3;
            public static int HandledException = 4;
            public static int RpcError = 5;
        }

        public static void TraceParameters(System.Collections.Specialized.NameValueCollection parameters)
        {
            if (_trace.Switch.Level >= SourceLevels.Verbose || _trace.Switch.Level == SourceLevels.All)
            {
                if (parameters != null && parameters.Count > 0)
                {
                    StringBuilder sb = new StringBuilder();
                    sb.AppendLine("Parameters:");
                    foreach (var item in parameters.AllKeys)
                    {
                        sb.AppendFormat("\t{0}: {1}\r\n", item, parameters[item]);
                    }
                    _trace.TraceEvent(TraceEventType.Verbose, EventID.Trace, sb.ToString());
                }
            }
        }

        public static void WriteMethodAndParmeters(Contracts.Request rpc)
        {
            var parameterstring = "";
            if (rpc.Parameters == null)
                return;
            Array.ForEach(rpc.Parameters, x => parameterstring += (parameterstring.Length > 0 ? ", " : "") + (x == null ? "null" : x.ToString()));
            _trace.TraceEvent(TraceEventType.Information, EventID.Trace, "MethodCall: {0}({1})", rpc.Method, parameterstring);
        }

        public static void WriteError(Contracts.Error error)
        {
            var err = error ?? new Error() { Code = -1, Data = "[no data]", Message = "[no message]" };
            _trace.TraceData(TraceEventType.Error, EventID.RpcError, string.Format("Error: {0}\n{1}", err.Message, err.Data));
        }
    }
}
